﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.IO;

namespace OptiGear1
{
    public class WowItem : ICloneable
    {
        public string name;
        public double weight;
        public string ilvl;
        public int wowheadid;
        public string bodypart;
        public string subclass;
        public string itemclass;
        public string source;
        public int spellpower;
        public int hit;
        public int haste;
        public int crit;
        public int spirit;
        public int intel;
        public int stamina;
        public int redsockets;
        public int bluesockets;
        public int yellowsockets;
        public int genericsockets;
        public int metasockets;
        public int bonus_spellpower;
        public int bonus_crit;
        public int bonus_haste;
        public int bonus_spirit;
        public int bonus_intel;
        public int bonus_stamina;
        public int bonus_hit;
        public int t7;
        public int t8;
        public int t9;
        public int t10;
        public bool isStaffEnchant;
        public int metaredreq;
        public int metabluereq;
        public int metayellowreq;
        public bool heroic;
        public bool priest;
        public bool warlock;
        public bool mage;

        private List<WowGem> gems;

        public string Name
        {
            get
            {
                return name;
            }
        }

        public string ItemClass
        {
            get
            {
                return itemclass;
            }
        }

        public string Subclass
        {
            get
            {
                return subclass;
            }
        }

        public bool Heroic
        {
            get
            {
                return heroic;
            }
        }

        public int RedGemCount
        {
            get
            {
                int count = 0;
                for (int i = 0; i < gems.Count; i++)
                {
                    if (gems[i].red > 0)
                        count++;
                }
                return count;
            }
        }

        public int BlueGemCount
        {
            get
            {
                int count = 0;
                for (int i = 0; i < gems.Count; i++)
                {
                    if (gems[i].blue > 0)
                        count++;
                }
                return count;
            }
        }

        public int YellowGemCount
        {
            get
            {
                int count = 0;
                for (int i = 0; i < gems.Count; i++)
                {
                    if (gems[i].yellow > 0)
                        count++;
                }
                return count;
            }
        }

        public List<WowGem> Gems
        {
            get
            {
                return gems;
            }
        }

        public WowItem()
        {
            gems = new List<WowGem>();
        }

        public WowItem(XmlNode node)
        {
            gems = new List<WowGem>();
            /*XmlDoc temp = new XmlDoc();
            temp.LoadXml(node.OuterXml);
            name = temp.GetNodeValue("//name");
            ilvl = temp.GetNodeValueIfExists("//ilvl");
            weight = temp.GetNodeValue("//weight");
            wowheadid = temp.GetNodeValue("//wowheadID");*/
        }

        public WowItem(int wowheadID, XmlDocument tierSets)
        {
            string itemurl = "http://www.wowhead.com/?item=" + wowheadID + "&xml";
            string itemXml = Utils.GetHtml(itemurl);

            XmlDoc itemDoc = new XmlDoc();
            itemDoc.LoadXml(itemXml);

            this.wowheadid = wowheadID;
            bodypart = itemDoc.GetNodeValue("//inventorySlot");
            subclass = itemDoc.GetNodeValue("//subclass");
            itemclass = itemDoc.GetNodeValue("//class");
            ilvl = itemDoc.GetNodeValue("//level");
            name = itemDoc.GetNodeValue("//name").Replace("'", "");
            heroic = false;

            hit = 0;
            spellpower = 0;
            haste = 0;
            crit = 0;
            spirit = 0;
            intel = 0;
            stamina = 0;

            //todo check if cloth
            priest = true;
            warlock = true;
            mage = true;

            if (itemXml.Contains("<br />Classes:"))
            {
                priest = false;
                warlock = false;
                mage = false;

                //special class restrictions on this item.
                int classesIndex = itemXml.IndexOf("<br />Classes:");
                int classesEndIndex = itemXml.Substring(classesIndex+14).IndexOf("<br />");
                string classesText = itemXml.Substring(classesIndex+14, classesEndIndex);
                string[] classes = classesText.Split(new char[] {','});
                for (int i = 0; i < classes.Length; i++)
                {
                    if (classes[i].Contains("Warlock"))
                        warlock = true;
                    if (classes[i].Contains("Priest"))
                        priest = true;
                    if (classes[i].Contains("Mage"))
                        mage = true;

                    /*switch (classes[i].Trim())
                    {
                        case("Priest"):
                            priest = true;
                            break;
                        case("Warlock"):
                            warlock = true;
                            break;
                        case("Mage"):
                            mage = true;
                            break;
                        default:
                            break;
                    }*/
                }
            }

            string dataValString = itemDoc.GetNodeValue("//jsonEquip");
            string[] dataVals = dataValString.Split(new char[] { ',' });
            for (int j = 0; j < dataVals.Length; j++)
            {
                string[] keyValuePair = dataVals[j].Split(new char[] { ':' });
                switch (keyValuePair[0])
                {
                    case ("\"critstrkrtng\""):
                        {
                            crit = Int32.Parse(keyValuePair[1]);
                            break;
                        }
                    case ("\"hitrtng\""):
                        {
                            hit = Int32.Parse(keyValuePair[1]);
                            break;
                        }
                    case ("\"splpwr\""):
                        {
                            spellpower = Int32.Parse(keyValuePair[1]);
                            break;
                        }
                    case ("\"int\""):
                        {
                            intel = Int32.Parse(keyValuePair[1]);
                            break;
                        }
                    case ("\"spi\""):
                        {
                            spirit = Int32.Parse(keyValuePair[1]);
                            break;
                        }
                    case ("\"sta\""):
                        {
                            stamina = Int32.Parse(keyValuePair[1]);
                            break;
                        }
                    case ("\"hastertng\""):
                        {
                            haste = Int32.Parse(keyValuePair[1]);
                            break;
                        }
                    default:
                        {
                            break;
                        }
                }
            }

            //now get socket bonus and sockets
            string toolTipString = itemDoc.GetNodeValue("//htmlTooltip");
            redsockets = toolTipString.Select((c, k) => toolTipString.Substring(k)).Count(sub => sub.StartsWith("Red Socket"));
            bluesockets = toolTipString.Select((c, k) => toolTipString.Substring(k)).Count(sub => sub.StartsWith("Blue Socket"));
            yellowsockets = toolTipString.Select((c, k) => toolTipString.Substring(k)).Count(sub => sub.StartsWith("Yellow Socket"));
            metasockets = toolTipString.Select((c, k) => toolTipString.Substring(k)).Count(sub => sub.StartsWith("Meta Socket"));
            isStaffEnchant = ( toolTipString.Select((c, k) => toolTipString.Substring(k)).Count(sub => sub.StartsWith("enchant a staff")) > 0);
            heroic = (toolTipString.Select((c, k) => toolTipString.Substring(k)).Count(sub => sub.StartsWith("Heroic")) > 0);
            if (bodypart == "Waist") //belt buckle
            {
                genericsockets++;
            }
            /*if (meta > 0) //assume ember skyflare. Ignore meta requirements.
            {
                spellpower += 25;
            }*/
            int bstart = toolTipString.IndexOf("Socket Bonus: +");
            if (bstart > 0)
            {
                toolTipString = toolTipString.Substring(bstart + 15);
                toolTipString = toolTipString.Substring(0, toolTipString.IndexOf("<"));
                string[] keyValuePair = toolTipString.Split(new char[] { ' ' });
                switch (keyValuePair[1])
                {
                    case ("Haste"):
                        {
                            bonus_haste = Int32.Parse(keyValuePair[0]);
                            break;
                        }
                    case ("Critical"):
                        {
                            bonus_crit = Int32.Parse(keyValuePair[0]);
                            break;
                        }
                    case ("Spirit"):
                        {
                            bonus_spirit = Int32.Parse(keyValuePair[0]);
                            break;
                        }
                    case ("Spell"):
                        {
                            bonus_spellpower = Int32.Parse(keyValuePair[0]);
                            break;
                        }
                    case ("Intellect"):
                        {
                            bonus_intel = Int32.Parse(keyValuePair[0]);
                            break;
                        }
                    case ("Stamina"):
                        {
                            bonus_stamina = Int32.Parse(keyValuePair[0]);
                            break;
                        }
                    case ("Hit"):
                        {
                            bonus_hit = Int32.Parse(keyValuePair[0]);
                            break;
                        }
                    default:
                        {
                            break;
                        }
                }
            }

            t7 = 0;
            t8 = 0;
            t9 = 0;
            t10 = 0;
            if (tierSets.SelectNodes("//t7[item='" + name + "']").Count > 0)
                t7 = 1;
            if (tierSets.SelectNodes("//t8[item='" + name + "']").Count > 0)
                t8 = 1;
            if (tierSets.SelectNodes("//t9[item='" + name + "']").Count > 0)
                t9 = 1;
            if (tierSets.SelectNodes("//t10[item='" + name + "']").Count > 0)
                t10 = 1;

            name += " (" + ilvl + ")"; //can't do this earlier or it'll mess up checking for tier set

            int sourceStart = itemDoc.GetNodeValue("//json").IndexOf(",n:'");
            if (sourceStart > 0)
            {
                sourceStart += 4;
                source = itemDoc.GetNodeValue("//json").Substring(sourceStart, itemDoc.GetNodeValue("//json").Length-sourceStart);
                source = source.Substring(0, source.IndexOf(",")-1);
            }
        }

        public void AddGem(WowGem gem)
        {
            gems.Add(gem);
        }

        public object Clone()
        {
            WowItem w = new WowItem();
            
            w.name = this.name;
            w.weight = this.weight;
            w.ilvl = this.ilvl;
            w.wowheadid = this.wowheadid;
            w.bodypart = this.bodypart;
            w.source = this.source;
            w.spellpower = this.spellpower;
            w.hit = this.hit;
            w.haste = this.haste;
            w.crit = this.crit;
            w.spirit = this.spirit;
            w.intel = this.intel;
            w.stamina = this.stamina;
            w.redsockets = this.redsockets;
            w.bluesockets = this.bluesockets;
            w.yellowsockets = this.yellowsockets;
            w.genericsockets = this.genericsockets;
            w.metasockets = this.metasockets;
            w.bonus_spellpower = this.bonus_spellpower;
            w.bonus_crit = this.bonus_crit;
            w.bonus_haste = this.bonus_haste;
            w.bonus_spirit = this.bonus_spirit;
            w.bonus_intel = this.bonus_intel;
            w.bonus_stamina = this.bonus_stamina;
            w.bonus_hit = this.bonus_hit;
            w.t7 = this.t7;
            w.t8 = this.t8;
            w.t9 = this.t9;
            w.t10 = this.t10;
            w.heroic = this.heroic;
            w.metaredreq = this.metaredreq;
            w.metabluereq = this.metabluereq;
            w.metayellowreq = this.metayellowreq;
            w.subclass = this.subclass;

            w.gems = new List<WowGem>();
            for (int i = 0; i < gems.Count; i++)
            {
                w.gems.Add(gems[i]);
            }
            return w;
        }

        public static List<WowItem> Deserialize(string fileName)
        {
            try
            {
                XmlSerializer mySerializer = new XmlSerializer(typeof(List<WowItem>));
                FileStream myFileStream = new FileStream(fileName, FileMode.Open);
                List<WowItem> wowitems = (List<WowItem>)mySerializer.Deserialize(myFileStream);
                myFileStream.Close();
                return wowitems;
            }
            catch (FileNotFoundException)
            {
                return new List<WowItem>();
            }
        }

        public static void Serialize(List<WowItem> items, string fileName)
        {
            XmlSerializer s = new XmlSerializer(typeof(List<WowItem>));
            TextWriter wr = new StreamWriter(fileName);
            s.Serialize(wr, items);
            wr.Close();
        }
    }

    class WowItemComparer : IComparer<WowItem>
    {
        public int Compare(WowItem item1, WowItem item2)
        {
            if (item1.hit == item2.hit)
                return item2.weight.CompareTo(item1.weight);
            else
                return item2.hit.CompareTo(item1.hit);
        }
    }

    class WowItemNameComparer : IComparer<WowItem>
    {
        public int Compare(WowItem item1, WowItem item2)
        {
            return item1.name.CompareTo(item2.name);
        }
    }
}
